package com.cskaoyan.mall.promo.service.impl;

import com.cskaoyan.mall.commons.constant.SysRetCodeConstants;
import com.cskaoyan.mall.commons.exception.BizException;
import com.cskaoyan.mall.commons.result.ServiceCallResponse;
import com.cskaoyan.mall.dto.ProductDetailDto;
import com.cskaoyan.mall.dto.ProductDetailServiceResponse;
import com.cskaoyan.mall.order.dto.CreateSeckillOrderRequest;
import com.cskaoyan.mall.promo.mq.producer.CreatePromoOrderProducer;
import com.cskaoyan.mall.promo.remote.OrderApiClient;
import com.cskaoyan.mall.promo.remote.ProductApiClient;
import com.cskaoyan.mall.promo.cache.CacheManager;
import com.cskaoyan.mall.promo.constant.PromoRetCode;
import com.cskaoyan.mall.promo.converter.PromoInfoConverter;
import com.cskaoyan.mall.promo.converter.PromoProductConverter;
import com.cskaoyan.mall.promo.dal.entitys.PromoItem;
import com.cskaoyan.mall.promo.dal.entitys.PromoSession;
import com.cskaoyan.mall.promo.dal.persistence.PromoItemMapper;
import com.cskaoyan.mall.promo.dal.persistence.PromoSessionMapper;
import com.cskaoyan.mall.promo.dto.*;
import com.cskaoyan.mall.promo.form.CreatePromoOrderRequest;
import com.cskaoyan.mall.promo.form.PromoProductDetailRequest;
import com.cskaoyan.mall.promo.service.PromoService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @Description
 **/
@Service
@Slf4j
public class PromoServiceImpl implements PromoService {

    @Autowired
    PromoSessionMapper sessionMapper;

    @Autowired
    PromoItemMapper promoItemMapper;

    @Autowired
    ProductApiClient productService;

    @Autowired
    PromoInfoConverter promoInfoConverter;

    @Autowired
    OrderApiClient orderPromoService;
    @Autowired
    PromoProductConverter promoProductConverter;


    @Autowired
    CacheManager cacheManager;

    @Autowired
    RedissonClient redissonClient;

    @Autowired
    CreatePromoOrderProducer producer;


    // 队列泄洪所使用的线程池
    ExecutorService executor;



    @Override
    public PromoInfoResponse getPromoList(Integer sessionId, String yyyymmdd) {
        PromoInfoResponse response = new PromoInfoResponse();

        log.info("start getPromoList sessionId = " + sessionId + ", yyyymmdd " + yyyymmdd);
        //查询场次信息
        Example promoSessionExample = new Example(PromoSession.class);
        promoSessionExample.createCriteria()
                .andEqualTo("sessionId", sessionId)
                .andEqualTo("yyyymmdd", yyyymmdd);
        List<PromoSession> sessionList = sessionMapper.selectByExample(promoSessionExample);


        if (CollectionUtils.isEmpty(sessionList)) {
            // 如果没找到秒杀场次
            throw new BizException(PromoRetCode.PROMO_NOT_EXIST.getCode(),
                    PromoRetCode.PROMO_NOT_EXIST.getMessage());
        }

        PromoSession promoSession = sessionList.get(0);

        Example promoItemExample = new Example(PromoItem.class);
        promoItemExample.createCriteria().andEqualTo("psId", promoSession.getId());
        List<PromoItem> promoItems = promoItemMapper.selectByExample(promoItemExample);

        List<PromoItemInfoDto> productList = new ArrayList<>();

        // 对该秒杀场次的每一个商品，查找其商品详情
        promoItems.stream().forEach(promoItem -> {
            Long itemId = promoItem.getItemId();

            ProductDetailServiceResponse productDetail = productService.getProductDetail(itemId);
            ProductDetailDto productDetailDto = productDetail.getCallData();
            PromoItemInfoDto promoItemInfoDto = promoInfoConverter.convert2InfoDto(productDetailDto,
                    promoItem.getItemStock(), promoItem.getSeckillPrice());
            productList.add(promoItemInfoDto);

        });

        //组装参数
        response.setPsId(promoSession.getId());
        response.setSessionId(sessionId);
        response.setProductList(productList);
        return response;
    }

    @Override
    @Transactional
    public void createPromoOrder(CreatePromoOrderRequest request) {

        List<PromoItem> promoItems = null;
        int effectiveRow = promoItemMapper.decreaseStock(request.getProductId(), request.getPsId());
        if (effectiveRow < 1) {
            // 秒杀商品售罄
            throw new BizException(PromoRetCode.PROMO_ITEM_STOCK_NOT_ENOUGH.getCode(),
                    PromoRetCode.PROMO_ITEM_STOCK_NOT_ENOUGH.getMessage());
        }

        //获取商品的秒杀价格
        Example example = new Example(PromoItem.class);
        example.createCriteria()
                .andEqualTo("psId", request.getPsId())
                .andEqualTo("itemId", request.getProductId());
        promoItems = promoItemMapper.selectByExample(example);

        if (CollectionUtils.isEmpty(promoItems)) {
            throw new BizException(PromoRetCode.PROMO_ITEM_NOT_EXIST.getCode(),
                    PromoRetCode.PROMO_ITEM_NOT_EXIST.getMessage());
        }

        PromoItem promoItem = promoItems.get(0);

        // 通过队列泄洪，保护下游服务即订单服务

        // 生成订单
        CreateSeckillOrderRequest createSeckillOrderRequest = new CreateSeckillOrderRequest();
        createSeckillOrderRequest.setUsername(request.getUsername());
        createSeckillOrderRequest.setUserId(request.getUserId());
        createSeckillOrderRequest.setProductId(request.getProductId());
        createSeckillOrderRequest.setPrice(promoItem.getSeckillPrice());
        createSeckillOrderRequest.setAddressId(request.getAddressId());
        createSeckillOrderRequest.setTel(request.getTel());
        createSeckillOrderRequest.setStreetName(request.getStreetName());


        ServiceCallResponse createSeckillOrderResponse =  orderPromoService.createPromoOrder(createSeckillOrderRequest);;


        if (SysRetCodeConstants.SERVICE_CALL_FAIL.getCode().equals(createSeckillOrderResponse.getCode())) {
            throw new BizException(createSeckillOrderResponse.getCode(), createSeckillOrderResponse.getMsg());
        }

    }

    @Override
    public void createPromoOrderInTransaction(CreatePromoOrderRequest request) {
        // 秒杀服务作为上游服务，发送事务消息

        List<PromoItem> promoItems = null;
        //获取商品的秒杀价格
        Example example = new Example(PromoItem.class);
        Long psId = request.getPsId();
        Long productId = request.getProductId();
        example.createCriteria()
                .andEqualTo("psId", psId)
                .andEqualTo("itemId", productId);
        promoItems = promoItemMapper.selectByExample(example);

        if (CollectionUtils.isEmpty(promoItems)) {
            throw new BizException(PromoRetCode.PROMO_ITEM_NOT_EXIST.getCode(),
                    PromoRetCode.PROMO_ITEM_NOT_EXIST.getMessage());
        }

        PromoItem promoItem = promoItems.get(0);


        // 生成订单参数
        CreateSeckillOrderRequest createSeckillOrderRequest = new CreateSeckillOrderRequest();
        createSeckillOrderRequest.setUsername(request.getUsername());
        createSeckillOrderRequest.setUserId(request.getUserId());
        createSeckillOrderRequest.setProductId(request.getProductId());
        createSeckillOrderRequest.setPrice(promoItem.getSeckillPrice());
        createSeckillOrderRequest.setAddressId(request.getAddressId());
        createSeckillOrderRequest.setTel(request.getTel());
        createSeckillOrderRequest.setStreetName(request.getStreetName());

        // 分布式事务，解决数据一致性问题

        // 发送包含秒杀订单参数的事务消息
        boolean success = producer.sendMessageCreateOrder(createSeckillOrderRequest, productId, psId);
        if (!success) {
            throw  new BizException(PromoRetCode.SEND_OR_LOCAL_TRANSACTION_FAIL.getCode(),
                    PromoRetCode.SEND_OR_LOCAL_TRANSACTION_FAIL.getMessage());
        }


    }


    @Override
    public PromoProductDetailDto getPromoProductDetail(PromoProductDetailRequest request) {


        Example example = new Example(PromoItem.class);
        example.createCriteria()
                .andEqualTo("psId", request.getPsId())
                .andEqualTo("itemId", request.getProductId());

        List<PromoItem> promoItems = promoItemMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(promoItems)) {
            throw new BizException(PromoRetCode.PROMO_ITEM_NOT_EXIST.getCode(),
                    PromoRetCode.PROMO_ITEM_NOT_EXIST.getMessage());
        }
        // 秒杀商品条目
        PromoItem promoItem = promoItems.get(0);

        ProductDetailServiceResponse productDetailServiceResponse = productService.getProductDetail(request.getProductId());
        if (SysRetCodeConstants.SERVICE_CALL_FAIL.getCode().equals(productDetailServiceResponse.getCode())) {
            throw new BizException(productDetailServiceResponse.getCode(),
                    productDetailServiceResponse.getMsg());

        }
        PromoProductDetailDto promoProductDetailDto
                = promoProductConverter.convert2DetailDto(promoItem, productDetailServiceResponse.getCallData());

        return promoProductDetailDto;
    }

}